﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SourceConvert
{
    public partial class Form1 : Form
    {
        int linecount = 0;
        List<string> lexts = new List<string>();
        List<string> files = new List<string>();
        List<string> txtlines = new List<string>();
        public Form1()
        {
            InitializeComponent();
        }
        private void fileSort()
        {
            Random random = new Random();
            List<string> newList = new List<string>();
            foreach (string item in files)
            {
                newList.Insert(random.Next(newList.Count), item);
            }
            files = newList;
        }

        private void btn_submit_Click(object sender, EventArgs e)
        {
            int line_max = int.Parse(txt_line.Text);
            if(line_max <= 0)
            {
                line_max = 4000;
            }
            if (linecount > line_max)
            {
                linkLabel1_LinkClicked(linkLabel1, null);
            }

            File.WriteAllText(Application.StartupPath + "/SC_Path.txt", txt_path.Text, Encoding.UTF8);

            string[] exts = txt_ext.Text.Split(';');
            string[] filter = txt_filter.Text.Split(';');
            string tmpstr;
            int ind, ind2;
            lexts.Clear();
            files.Clear();
            foreach (string ext in exts)
            {
                tmpstr = ext.Trim();
                if(tmpstr.StartsWith("*."))
                    lexts.Add(tmpstr.Substring(2).ToLower());
            }
            if (lexts.Count == 0)
            {
                MessageBox.Show("扩展名没有设置");
                return;
            }
            string[] paths = txt_path.Lines;
            btn_submit.Enabled = false;
            try
            {
                foreach(string path in paths)
                    dirrun(path);
                fileSort();
                foreach (string file in files)
                {
                    //rtb_source.AppendText(file + Environment.NewLine + Environment.NewLine + Environment.NewLine + Environment.NewLine + Environment.NewLine);
                    ind = file.LastIndexOf('.');
                    if (ind == -1)
                        continue;
                    tmpstr = file.Substring(ind + 1).ToLower();

                    if (lexts.Contains(tmpstr))
                    {
                        Encoding encode = TxtFileEncoding.getencode_percent(File.ReadAllBytes(file));
                        string[] lines = File.ReadAllLines(file, encode);
                        bool bst = false;
                        foreach (string line in lines)
                        {
                            string linen = line;
                            if (bst)//前面遇到了/*
                            {
                                ind2 = linen.IndexOf("*/");
                                if (ind2 == -1)
                                    continue;
                                else
                                {
                                    linen = linen.Substring(ind2 + 2);
                                    bst = false;
                                }
                            }
                            else
                            {
                                ind = linen.IndexOf("/*");
                                if (ind > -1)
                                {
                                    ind2 = linen.IndexOf("*/", ind);
                                    if (ind2 > 0)
                                    {
                                        linen = linen.Remove(ind, ind2 - ind + 2);
                                    }
                                    else
                                    {
                                        linen = linen.Remove(ind);
                                        bst = true;
                                    }
                                }
                            }
                            ind = linen.IndexOf("//");
                            if (ind > -1)
                                linen = linen.Remove(ind);
                            tmpstr = linen.Trim();

                            //
                            foreach (string f in filter)
                            {
                                if (tmpstr.StartsWith(f))
                                {
                                    tmpstr = "";
                                    break;
                                }
                                 
                            }

                            if (tmpstr == "")
                                continue;

                            txtlines.Add(linen);
                            linecount++;
                        }
                    }
                    Application.DoEvents();
                    if (linecount > line_max)
                        break;
                }
                if (txtlines.Count > line_max)
                {
                    txtlines.RemoveRange(30 * 50, txtlines.Count - 60 * 50);
                }
                rtb_source.Lines = txtlines.ToArray();
            }
            catch (Exception ex)
            {
                MessageBox.Show("运行错误:" + ex.Message);
                return;
            }
            finally
            {
                btn_submit.Enabled = true;
            }
            int page = (int)Math.Ceiling(linecount * 1.0 / 50);
            lab_msg.Text = linecount + "行," + page + "页";
        }
        private void dirrun(string path)
        {
            if (path.Trim() == "")
                return;
            if(!Directory.Exists(path))
                return;
            files.AddRange(Directory.GetFiles(path));

            string[] dirs = Directory.GetDirectories(path);
            foreach (string dir in dirs)
            {
                dirrun(dir);
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            linecount = 0;
            rtb_source.Clear();
            txtlines.Clear();
            lab_msg.Text = "";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (File.Exists(Application.StartupPath + "/SC_Path.txt"))
                txt_path.Text = File.ReadAllText(Application.StartupPath + "/SC_Path.txt", Encoding.UTF8);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            label3.Left = txt_ext.Left + txt_ext.Width + 5;
            txt_line.Left = label3.Left + label3.Width + 5;
            txt_line.Width = txt_path.Left + txt_path.Width - txt_line.Left;
        }
    }
    public class TxtFileEncoding
    {
        public static Encoding getencode_percent(byte[] lb)
        {
            try
            {
                if (is_utf8_code(lb))
                    return Encoding.UTF8;
                if (is_gb2312_code(lb))
                    return Encoding.GetEncoding("gb2312");
                if (is_big5_code(lb))
                    return Encoding.GetEncoding("big5");
                if (is_gbk_code(lb))
                    return Encoding.GetEncoding("gbk");
            }
            catch (Exception ex)
            {
            }
            return Encoding.ASCII;
        }
        public static bool is_utf8_special_byte(byte c)
        {
            byte special_byte = 0X02; //binary 00000010    
            if (c >> 6 == special_byte)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool is_utf8_code(byte[] byts)
        {
            byte one_byte = 0X00; //binary 00000000
            byte two_byte = 0X06; //binary 00000110
            byte three_byte = 0X0E; //binary 00001110  
            byte four_byte = 0X1E; //binary 00011110
            byte five_byte = 0X3E; //binary 00111110
            byte six_byte = 0X7E; //binary 01111110

            int utf8_yes = 0;
            int utf8_no = 0;

            byte k = 0;
            byte m = 0;
            byte n = 0;
            byte p = 0;
            byte q = 0;

            byte c = 0;
            for (int i = 0; i < byts.Length; )
            {
                c = byts[i];
                if (c >> 7 == one_byte)
                {
                    i++;
                    continue;
                }
                else if (c >> 5 == two_byte)
                {
                    k = byts[i + 1];
                    if (is_utf8_special_byte(k))
                    {
                        utf8_yes++;
                        i += 2;
                        continue;
                    }
                }
                else if (c >> 4 == three_byte)
                {
                    m = byts[i + 1];
                    n = byts[i + 2];
                    if (is_utf8_special_byte(m)
                            && is_utf8_special_byte(n))
                    {
                        utf8_yes++;
                        i += 3;
                        continue;
                    }
                }
                else if (c >> 3 == four_byte)
                {
                    k = byts[i + 1];
                    m = byts[i + 2];
                    n = byts[i + 3];
                    if (is_utf8_special_byte(k)
                            && is_utf8_special_byte(m)
                            && is_utf8_special_byte(n))
                    {
                        utf8_yes++;
                        i += 4;
                        continue;
                    }
                }
                else if (c >> 2 == five_byte)
                {
                    k = byts[i + 1];
                    m = byts[i + 2];
                    n = byts[i + 3];
                    p = byts[i + 4];
                    if (is_utf8_special_byte(k)
                            && is_utf8_special_byte(m)
                            && is_utf8_special_byte(n)
                            && is_utf8_special_byte(p))
                    {
                        utf8_yes++;
                        i += 5;
                        continue;
                    }
                }
                else if (c >> 1 == six_byte)
                {
                    k = byts[i + 1];
                    m = byts[i + 2];
                    n = byts[i + 3];
                    p = byts[i + 4];
                    q = byts[i + 5];
                    if (is_utf8_special_byte(k)
                            && is_utf8_special_byte(m)
                            && is_utf8_special_byte(n)
                            && is_utf8_special_byte(p)
                            && is_utf8_special_byte(q))
                    {
                        utf8_yes++;
                        i += 6;
                        continue;
                    }
                }

                utf8_no++;
                i++;
            }
            if (utf8_yes + utf8_no == 0)
                return false;
            int ret = (100 * utf8_yes) / (utf8_yes + utf8_no);
            if (ret > 90)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool is_gb2312_code(byte[] byts)
        {
            byte one_byte = 0X00; //binary 00000000

            int gb2312_yes = 0;
            int gb2312_no = 0;

            byte k = 0;

            byte c = 0;
            for (int i = 0; i < byts.Length; )
            {
                c = byts[i];
                if (c >> 7 == one_byte)
                {
                    i++;
                    continue;
                }
                else if (c >= 0XA1 && c <= 0XF7)
                {
                    k = byts[i + 1];
                    if (k >= 0XA1 && k <= 0XFE)
                    {
                        gb2312_yes++;
                        i += 2;
                        continue;
                    }
                }

                gb2312_no++;
                i += 2;
            }
            if (gb2312_yes + gb2312_no == 0)
                return false;
            int ret = (100 * gb2312_yes) / (gb2312_yes + gb2312_no);
            if (ret > 90)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool is_big5_code(byte[] byts)
        {
            byte one_byte = 0X00; //binary 00000000

            int big5_yes = 0;
            int big5_no = 0;

            byte k = 0;

            byte c = 0;
            for (int i = 0; i < byts.Length; )
            {
                c = byts[i];
                if (c >> 7 == one_byte)
                {
                    i++;
                    continue;
                }
                else if (c >= 0XA1 && c <= 0XF9)
                {
                    k = byts[i + 1];
                    if (k >= 0X40 && k <= 0X7E
                            || k >= 0XA1 && k <= 0XFE)
                    {
                        big5_yes++;
                        i += 2;
                        continue;
                    }
                }

                big5_no++;
                i += 2;
            }

            if (big5_yes + big5_no == 0)
                return false;
            int ret = (100 * big5_yes) / (big5_yes + big5_no);
            if (ret > 90)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool is_gbk_code(byte[] byts)
        {
            byte one_byte = 0X00; //binary 00000000

            int gbk_yes = 0;
            int gbk_no = 0;

            byte k = 0;

            byte c = 0;
            for (int i = 0; i < byts.Length; )
            {
                c = byts[i];
                if (c >> 7 == one_byte)
                {
                    i++;
                    continue;
                }
                else if (c >= 0X81 && c <= 0XFE)
                {
                    k = byts[i + 1];
                    if (k >= 0X40 && k <= 0XFE)
                    {
                        gbk_yes++;
                        i += 2;
                        continue;
                    }
                }

                gbk_no++;
                i += 2;
            }

            if (gbk_yes + gbk_no == 0)
                return false;
            int ret = (100 * gbk_yes) / (gbk_yes + gbk_no);
            if (ret > 90)
                return true;
            else
                return false;
        }
    }

}
